/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

import { expect } from '@jest/globals';
import * as fs from 'fs';
import { copy } from 'fs-extra';
import * as path from 'path';

import { appRoot, initByStageEmptyApp, initExecuteCommand, runHvigor } from '../../common/common';
import { FormConfigModifier } from '../../common/modifier/form-config-modifier';
import { PackageJsonModifier } from '../../common/modifier/package-json-modifier';
import { Probes } from '../../common/probes';

const prepareHook = async (dir: string) => {
  const entryPackageJson = new PackageJsonModifier(dir, 'entry');
  entryPackageJson.updateDependency('library', 'file:../library');
  entryPackageJson.outputSync();

  // 更新library的main入口
  const libraryPackageJson = new PackageJsonModifier(dir, 'library');
  libraryPackageJson.updateMainField('./index.ets');
  libraryPackageJson.outputSync();

  const entryPageIndexEtsFilePath = path.resolve(dir, 'entry/src/main/ets/pages/index.ets');

  // 修改entry源码,依赖library中的接口
  fs.writeFileSync(entryPageIndexEtsFilePath, 'import { test } from \'library\'\n' +
    'test();\n' +
    'import {MainPage} from \'library\'\n' +
    '    MainPage().build()\n' +
    '\n' +
    '@Entry\n' +
    '@Component\n' +
    'struct Index {\n' +
    '  @State message: string = \'Hello World\'\n' +
    '\n' +
    '  build() {\n' +
    '    Row() {\n' +
    '      Column() {\n' +
    '        Text(this.message)\n' +
    '          .fontSize(50)\n' +
    '          .fontWeight(FontWeight.Bold)\n' +
    '      }\n' +
    '      .width(\'100%\')\n' +
    '    }\n' +
    '    .height(\'100%\')\n' +
    '  }\n' +
    '}');
};
const commands = initExecuteCommand({
  mode: 'module',
  product: 'default',
  module: 'entry',
  tasks: 'default@CompileArkTS',
  log: 'd'
});


describe('test compile stage ark ts', () => {
  test.concurrent('test stage mode incremental compile arkTs and change library main field', async () => {
    await initByStageEmptyApp({
      prepare: prepareHook,
      cb: async (projectRoot) => {
        // 第一次执行 expect Finish
        const result = runHvigor(projectRoot, commands);
        expect(result.stdout).toContain('runtimeOS:');
        expect(result.stdout).toContain('sdkInfo:');
        expect(result.stdout).toContain('Finished :entry:default@CompileArkTS...');
        expect(result.stdout).toContain('BUILD SUCCESSFUL');

        // 第二次执行 expect UpToDate
        const executeAgainResult = runHvigor(projectRoot, commands);
        expect(executeAgainResult.stdout).toContain('UP-TO-DATE :entry:default@CompileArkTS...');
        expect(executeAgainResult.stdout).toContain('BUILD SUCCESSFUL');

        // 更新library中的index.ets中的源码
        const libraryIndexEtsFilePath = path.resolve(projectRoot, 'library/index.ets');
        fs.writeFileSync(libraryIndexEtsFilePath, 'export function test() {\n' +
          '  const aa = "aa"\n' +
          '  const bb = "bb"\n' +
          '  return bb\n' +
          '}\n' +
          '\n' +
          'export { MainPage } from \'./src/main/ets/components/mainpage/MainPage\'\n');

        // 重新执行
        const executeAgainResultAfterDelete = runHvigor(projectRoot, commands);
        expect(executeAgainResultAfterDelete.stdout).toContain('Finished :entry:default@CompileArkTS...');
        expect(executeAgainResultAfterDelete.stdout).toContain('BUILD SUCCESSFUL');
      },
      runNpmInstall: true
    });
  });
  test.concurrent('test stage mode incremental compile arkTs and change library src/main', async () => {
    await initByStageEmptyApp({
      prepare: prepareHook,
      cb: async (projectRoot) => {
        // 第一次执行 expect Finish
        const result = runHvigor(projectRoot, commands);
        expect(result.stdout).toContain('Finished :entry:default@CompileArkTS...');
        expect(result.stdout).toContain('BUILD SUCCESSFUL');

        // 第二次执行 expect UpToDate
        const executeAgainResult = runHvigor(projectRoot, commands);
        expect(executeAgainResult.stdout).toContain('UP-TO-DATE :entry:default@CompileArkTS...');
        expect(executeAgainResult.stdout).toContain('BUILD SUCCESSFUL');

        // 更新library中的index.ets中的源码
        const libraryIndexEtsFilePath = path.resolve(projectRoot,
          'library/src/main/ets/components/MainPage/MainPage.ets');
        fs.writeFileSync(libraryIndexEtsFilePath, 'import hilog from \'@ohos.hilog\';\n' +
          'import testNapi from \'liblibrary.so\'\n' +
          '\n' +
          '@Component\n' +
          'export struct MainPage {\n' +
          '  @State message: string = \'xxxxxxxxxxxxxxxxxxxxxxxx\'\n' +
          '\n' +
          '  build() {\n' +
          '    Row() {\n' +
          '      Column() {\n' +
          '        Text(this.message)\n' +
          '          .fontSize(50)\n' +
          '          .fontWeight(FontWeight.Bold)\n' +
          '          .onClick(() => {\n' +
          '            hilog.isLoggable(0x0000, \'testTag\', hilog.LogLevel.INFO);\n' +
          '            hilog.info(0x0000, \'testTag\', \'Test NAPI 2 + 3 = %{public}s\', testNapi.add(2, 3));\n' +
          '          })\n' +
          '      }\n' +
          '      .width(\'100%\')\n' +
          '    }\n' +
          '    .height(\'100%\')\n' +
          '  }\n' +
          '}');

        // 重新执行
        const executeAgainResultAfterDelete = runHvigor(projectRoot, commands);
        expect(executeAgainResultAfterDelete.stdout).toContain('Finished :entry:default@CompileArkTS...');
        expect(executeAgainResultAfterDelete.stdout).toContain('BUILD SUCCESSFUL');
      },
      runNpmInstall: true
    });
  });

  // 依赖rollup转测后配套的arkTS编译SDK
  test.concurrent('test stage arkTs widget compile', async () => {
    await initByStageEmptyApp({
      prepare: async (dir: string) => {
        // change arkTs config
        const entryFormConfig = new FormConfigModifier(dir, 'entry');
        entryFormConfig.setUiSyntax('arkts');
        entryFormConfig.setSrc('./ets/widget/pages/card.ets');
        entryFormConfig.outputSync();

        // copy ark ts widget file
        await copy(path.resolve(appRoot(), 'test/resources/extra/arkTs_widget'),
          `${dir}/entry/src/main/ets`);
      },
      cb: async (projectRoot) => {
        commands.push('--stacktrace');
        const result = runHvigor(projectRoot, commands);
        expect(result.stdout).toContain('Finished :entry:default@CompileArkTS...');
        expect(result.stdout).toContain('BUILD SUCCESSFUL');

        // expect widgets.abc
        const probes = new Probes(projectRoot, path.resolve(projectRoot, 'entry'));
        const outDir = path.resolve(probes.getIntermediatesLoaderOutPath(), 'ets');
        expect(fs.readdirSync(outDir)).toContain('widgets.abc');
      },
      runNpmInstall: true
    });
  });
});
